// PrimalView.m

#import "PrimalView.h"
#import "Controller.h"

@implementation PrimalView

- mouseDown: (NXEvent *)event
{
	NXPoint mouseLocation;
	
	mouseLocation = event->location;
	[self convertPoint:&mouseLocation fromView:nil];
	mouseLocation.x = xMin + mouseLocation.x / bounds.size.width * (xMax - xMin);
	mouseLocation.y = yMin + mouseLocation.y / bounds.size.height * (yMax - yMin);
	[controller addPrimal:mouseLocation];
	return self;
}

#define X(x) ((x - xMin) * sx)
#define Y(y) ((y - yMin) * sy)

- drawSelf:(const NXRect *)rects :(int)rectCount
{
	PointLine *primalPoint, *primalLine;
	int numberOfPrimalPoints, numberOfPrimalLines;
	int i;
	float sx = bounds.size.width / (xMax - xMin);
	float sy = bounds.size.height / (yMax - yMin);
	
	[super drawSelf:rects :rectCount];

	// draw primal points
	[controller getPrimalPoints:&numberOfPrimalPoints :&primalPoint];
	for (i = 0; i < numberOfPrimalPoints; i++) {
		NXSetColor(primalPoint[i].color);
		if ([showLabels state]) {
			PSmoveto(X(primalPoint[i].a), Y(primalPoint[i].b));
			PSshow(primalPoint[i].label);
		}
		PSnewpath();
		PSarc(X(primalPoint[i].a), Y(primalPoint[i].b), 2.0, 0.0, 360.0);
		PSfill();
	}

	// draw primal lines
	[controller getPrimalLines:&numberOfPrimalLines :&primalLine];
	for (i = 0; i < numberOfPrimalLines; i++) {
		float x = xMin;
		float y = x * primalLine[i].a + primalLine[i].b;
		int dy = 0;		// used to adjust the position of the line label
		if (y < yMin && primalLine[i].a) {
			y = yMin;
			x = (y - primalLine[i].b) / primalLine[i].a;
		} else if (y > yMax && primalLine[i].a) {
			y = yMax;
			x = (y - primalLine[i].b) / primalLine[i].a;
			dy = -12;
		}
		NXSetColor(primalLine[i].color);
		if ([showLabels state]) {
			PSmoveto(X(x), Y(y) + dy);
			PSshow(primalLine[i].label);
		}
		PSmoveto(X(xMin), Y(xMin * primalLine[i].a + primalLine[i].b));
		PSlineto(X(xMax), Y(xMax * primalLine[i].a + primalLine[i].b));
		PSstroke();
	}
	
	return self;
}

@end
